﻿using System.Collections.Generic;
using SymbolIntegration.core.Helpers;

namespace SymbolIntegration.core.Expressions.Functions
{
    public class IntegrFunction : Expression
    {
        private Expression m_Argument;
        private readonly string m_Var;
        public IntegrFunction(Expression argument, string variable)
        {
            m_Argument = argument;
            m_Var = variable;
        }

        public override Expression Clone()
        {
            var clone = new IntegrFunction(m_Argument, m_Var);
            InnerCopy(clone);
            return clone;
        }

        public override ExpressionType Type
        {
            get { return ExpressionType.Integration; }
        }

        public override Expression Substitute(Dictionary<string, Expression> varValues)
        {
            Expression result = new SubstituteFunction(this, varValues);
            return result;
        }

        public override Expression Differentiate(string variable)
        {
            Expression result;
            if (variable == m_Var)
            {
                result = m_Argument.InvertNegate(IsNegate);
            }
            else
            {
                result = new DifferentiateFunction(this, variable);
            }
            return result;
        }

        public override Expression Normalize()
        {
            var normalized = new IntegrFunction(m_Argument.Normalize(), m_Var);
            InnerCopy(normalized);
            return normalized;
        }

        public override bool IsEqual(Expression right)
        {
            bool result = right.Type == Type && right.IsNegate == IsNegate;
            var integrExpressionRight = right as IntegrFunction;
            if (result && integrExpressionRight != null)
            {
                result = integrExpressionRight.m_Argument.IsEqual(m_Argument) && integrExpressionRight.m_Var == m_Var;
            }

            return result;
        }

        public override Polinom FormatToPolinomAsDependentFromVariable(string variable)
        {
            return null;
        }

        public override string ToString()
        {
            var result = "I";
            result += "(" + m_Argument + "," + m_Var + ")";
            return result;
        }

        protected internal override void RebuildDependancyCache()
        {
            if (!m_Argument.m_Cache.IsValid)
            {
                m_Argument.RebuildDependancyCache();
            }
            m_Cache.Varibles.UnionWith(m_Argument.m_Cache.Varibles);
            m_Cache.Varibles.Add(m_Var);
        }

        protected internal override void FillExpressionStatistic(ExpressionStatistic statistic, string integrateVariable)
        {
            m_Argument.FillExpressionStatistic(statistic, integrateVariable);
            statistic.HasUnintegratedExpression = true;
        }

        protected internal override Expression IntegrateAsDependentFromVar(string variable, IIntegrator integrator)
        {
            Expression result = new IntegrFunction(SetNegate(false), variable).SetNegate(IsNegate);
            return result;
        }
    }
}